using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.Entities.ScreeningTool;
using Sustainalytics.ScreeningTool.Synchronization.Entities;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.ScreeningTool.Synchronization.Caches
{
    public class FieldDefinitionsCache : DictionaryCache<string, FieldDefinition>
    {
        public bool ContainsField(string key, bool companyIsCoverage)
            => dictionary.ContainsKey(key) && (!companyIsCoverage || dictionary[key].HasOwnValue);

        public bool ContainsFieldWithValueFromParent(string key)
            => dictionary.ContainsKey(key) && !dictionary[key].HasOwnValue;

        public bool IsResearchAvailable(string key, ResearchStates researchStates)
        {
            if (researchStates == null)
                return false;

            var fieldDefinition = GetValueOrEmpty(key, null);
            if (fieldDefinition == null)
                return false;

            if (fieldDefinition.ResearchProducts == null || !fieldDefinition.ResearchProducts.Any())
                return true;

            var researchState = fieldDefinition.ResearchProducts.GetResearchState(researchStates);
            return researchState == ResearchState.ResearchAvailable;
        }
    }

    public class FieldDefinitionCacheLoader : ICacheLoader<FieldDefinitionsCache>
    {
        private readonly FieldDefinitionsCache cache;
        private readonly IMongoCollection<FieldDefinition> collection;

        public FieldDefinitionCacheLoader(FieldDefinitionsCache cache, IMongoCollection<FieldDefinition> collection)
        {
            this.cache = cache;
            this.collection = collection;
        }

        public async Task LoadAsync(ClientFacingProduct clientFacingProduct)
        {
            var result = await collection.Find(_ => true).ToListAsync().ConfigureAwait(false);

            var items = result
                .GroupBy(x => x.Key)
                .ToDictionary(grp => grp.Key, grp => grp.First());

            cache.AddItems(items);
        }
    }
}
